package com.future;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Description:
 * 根据百度百科，生命游戏，简称为生命，是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
 * <p>
 * 给定一个包含 m × n 个格子的面板，每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态：1 即为活细胞（live），或 0 即为死细胞（dead）。每个细胞与其八个相邻位置（水平，垂直，对角线）的细胞都遵循以下四条生存定律：
 * <p>
 * 如果活细胞周围八个位置的活细胞数少于两个，则该位置活细胞死亡；
 * 如果活细胞周围八个位置有两个或三个活细胞，则该位置活细胞仍然存活；
 * 如果活细胞周围八个位置有超过三个活细胞，则该位置活细胞死亡；
 * 如果死细胞周围正好有三个活细胞，则该位置死细胞复活；
 * 下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的，其中细胞的出生和死亡是同时发生的。给你 m x n 网格面板 board 的当前状态，返回下一个状态。
 * <p>
 * 示例
 * 1、
 * 输入：board = [[0,1,0],[0,0,1],[1,1,1],[0,0,0]]
 * 输出：[[0,0,0],[1,0,1],[0,1,1],[0,1,0]]
 * 2、
 * 输入：board = [[1,1],[1,0]]
 * 输出：[[1,1],[1,1]]
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/game-of-life
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 *
 * @author weiruibai.vendor
 * Date: 2021/9/28 16:07
 */
public class Solution_gameOfLife_289 {

    public static void main(String[] args) {
        int[][] board = {{0, 1, 0}, {0, 0, 1}, {1, 1, 1}, {0, 0, 0}};
        board = new int[][]{{1, 1}, {1, 0}};
        for (int i = 0; i < board.length; i++) {
            System.out.println(Arrays.toString(board[i]));
        }
        gameOfLife(board);
        System.out.println("整理后");
        for (int i = 0; i < board.length; i++) {
            System.out.println(Arrays.toString(board[i]));
        }
    }

    /**
     * 活1: sum<2 => 0
     * 活1：sum=2|3 => 1
     * 活1：sum>3 => 0
     * 死0：sum=3 => 1
     *
     * @param board
     */
    public static void gameOfLife(int[][] board) {
        if (board == null || board.length <= 0) {
            return;
        }
        // 收集由1=》0的坐标点
        List<Integer[]> zeroList = new ArrayList<>();
        // 收集由0=》1的坐标点
        List<Integer[]> oneList = new ArrayList<>();
        int row = board.length;
        int col = board[0].length;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                int sum = getSum(i, j, board);
                int val = board[i][j];
                if (val == 1) {
                    /**
                     * 活1: sum<2 => 0
                     * 活1：sum=2|3 => 1 （可以忽略，没有变化）
                     * 活1：sum>3 => 0
                     */
                    if (sum < 2 || sum > 3) {
                        // 由于本身为1，所以只考虑修改为0的情况
                        zeroList.add(new Integer[]{i, j});
                    }
                } else {
                    /**
                     * 死0：sum=3 => 1
                     */
                    if (sum == 3) {
                        oneList.add(new Integer[]{i, j});
                    }
                }
            }
        }
        // 统一设值
        if (zeroList != null || zeroList.size() > 0) {
            for (int i = 0; i < zeroList.size(); i++) {
                int r = zeroList.get(i)[0];
                int c = zeroList.get(i)[1];
                board[r][c] = 0;
            }
        }
        if (oneList != null || oneList.size() > 0) {
            for (int i = 0; i < oneList.size(); i++) {
                int r = oneList.get(i)[0];
                int c = oneList.get(i)[1];
                board[r][c] = 1;
            }
        }
    }

    private static int getSum(int row, int col, int[][] board) {
        int R = board.length;
        int C = board[0].length;
        int sum = 0;
        // 当前行前一行三个
        if (row - 1 >= 0) {
            sum += board[row - 1][col]; //正上方一个
            if (col - 1 >= 0) {
                sum += board[row - 1][col - 1];//左上角
            }
            if (col + 1 < C) {
                sum += board[row - 1][col + 1];//右上角
            }
        }
        // 当前行
        if (col - 1 >= 0) { // 左一
            sum += board[row][col - 1];
        }
        if (col + 1 < C) { // 右一
            sum += board[row][col + 1];
        }
        // 下一行三个
        if (row + 1 < R) {
            sum += board[row + 1][col]; // 正下方
            if (col - 1 >= 0) { // 左下角
                sum += board[row + 1][col - 1];
            }
            if (col + 1 < C) {
                sum += board[row + 1][col + 1];
            }
        }
        return sum;
    }


}
